import * as path from 'path';
import * as vscode from 'vscode';
import { GiteeApi, Project, Branches } from './giteeApi';

export class ProjectProvider implements vscode.TreeDataProvider<vscode.TreeItem> {

  private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined> = new vscode.EventEmitter<ProjectItem | undefined>();
  readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined> = this._onDidChangeTreeData.event;
  private page = 1;
  private treeList: vscode.TreeItem[] = [];
  private moreLock = false;

  constructor(private api: GiteeApi) {
    this.getMoreProject().then(() => {
      this._onDidChangeTreeData.fire(undefined);
    });
  }

  public async getChildren(element?: ProjectItem): Promise<vscode.TreeItem[]> {
    if (element) {
      return this.getAllBranch(element.project);
    }
    return this.treeList;
  }

  public async refresh() {
    this.page = 1;
    this.treeList = [];
    await this.getMoreProject();
    this._onDidChangeTreeData.fire(undefined);
  }

  public getTreeItem(element: ProjectItem): ProjectItem {
    return element;
  }

  public async create() {
    try {
      const name = await vscode.window.showInputBox({ placeHolder: '请输入仓库名称' });
      if (!name) {
        return;
      }
      const isPrivate = await vscode.window.showInputBox({ placeHolder: '仓库是否私有？默认为公开，true/false' });
      const description = await vscode.window.showInputBox({ placeHolder: '仓库描述' });
      const project = await this.api.createProject(name, isPrivate === 'true', description);
      vscode.window.showInformationMessage(`${ project.name }创建成功！`);
      this.refresh();
    } catch (error) {
      vscode.window.showErrorMessage(`创建仓库失败: ${ error.toString() }`);
    }
  }

  public async delete(node: ProjectItem) {
    try {
      const project = node.project;
      const name = await vscode.window.showInputBox({ placeHolder: `请输入仓库名【${ project.name }】称确认` });
      if (name !== project.name) {
        vscode.window.showErrorMessage('名称错误，请重试！');
        return;
      }
      const result = await vscode.window.showWarningMessage(`该操作将永久删除仓库【${ project.name }】且无法逆转，确认继续吗？`, '确定', '取消');
      if (result !== '确定') {
        return;
      }
      await this.api.deleteProject(project.owner.login, project.path);
      vscode.window.showInformationMessage(`仓库【${ project.name }】已删除!`);
      this.refresh();
    } catch (error) {
      vscode.window.showErrorMessage(`删除仓库失败: ${ error.toString() }`);
    }
  }

  public async more() {
    if (this.moreLock) {
      return;
    }
    this.moreLock = true;
    this.treeList.pop();
    await this.getMoreProject();
    this._onDidChangeTreeData.fire(undefined);
    this.moreLock = false;
  }

  private async getMoreProject() {
    try {
      const list = await this.api.getProjectList(this.page, this.limit);
      for (const item of list) {
        this.treeList.push(new ProjectItem(item, vscode.TreeItemCollapsibleState.Collapsed));
      }
      if (list.length > 0) {
        const more = new vscode.TreeItem('... 加载更多');
        more.command = {
          title: '加载更多',
          command: 'gitee.moreProject',
        };
        this.treeList.push(more);
      }
      this.page ++;
    } catch (error) {
      vscode.window.showErrorMessage(`获取仓库列表失败: ${ error.toString() }`);
    }
  }

  private async getAllBranch(project: Project) {
    try {
      const treeItemList = [];
      const list = await this.api.getAllBranches(project.owner.login, project.path);
      for (const item of list) {
        treeItemList.push(new BranchItem(item));
      }
      return treeItemList;
    } catch (error) {
      vscode.window.showErrorMessage(`获取仓库分支失败: ${ error.toString() }`);
      return [];
    }
  }

  private get limit() {
    return vscode.workspace.getConfiguration('gitee').get<number>('projectLimit') || 50;
  }
}

export class ProjectItem extends vscode.TreeItem {
  constructor(public project: Project, public readonly collapsibleState: vscode.TreeItemCollapsibleState) {
    super(project.name, collapsibleState);
    this.project = project;
    this.description = project.description;
    this.iconPath = path.join(__dirname, `../media/${ project.private ? 'private' : 'public' }.svg`);
    this.contextValue = 'project';
  };
}

export class BranchItem extends vscode.TreeItem {

  constructor(public branch: Branches) {
    super(branch.name);
    this.branch = branch;
    this.iconPath = path.join(__dirname, '../media/branch.svg');
  };
}